function MarkerCollectionOptions(add, del, options, state, map, infowindow) {
  var that = this;
  this.state = state;
  this.map = map;
  this.infowindow = infowindow;
  this.add = add.click(function(e) {
    that.addCollection('Untitled');
    return e.preventDefault();
  });
  this.del = del.click(function(e) {
    that.deleteCollection(state.selectedCollection);
    return e.preventDefault();
  });
  this.options = options.bind("change", function() {
    that.updateCollection();
  });
}

MarkerCollectionOptions.prototype.parseOptions = function() {
  var markerOptions = {};
  $('#markeroptions input[type=checkbox]').each(function() {
    var input = $(this);
    markerOptions[input.attr('name')] = input.attr('checked');
  });
  $('#markeroptions input[type=text]').each(function() {
    var input = $(this);
    markerOptions[input.attr('name')] = input.attr('value');
  });

  return markerOptions;
};

MarkerCollectionOptions.prototype.updateOptions = function(collection) {
  var textOptions = ['icon', 'shadow'];
  var options = collection.getOptions();
  for (var option in options) {
    var attr = option in textOptions ? 'value' : 'checked';
    $('#markeroptions input[name=' + option + ']').attr(attr, options[option]);
  }

  $('#marker-collections .selected img').attr(
      'src', options['icon'] || markerUrl);

  $('#collection-name').attr('value', collection.name);
};

MarkerCollectionOptions.prototype.updateCollection = function() {
  var name = this.state.selectedCollection;
  if (!name) return;

  var collection = this.state.markerCollections[name];
  if (!collection) return;

  var markerOptions = this.parseOptions();
  collection.setOptions(markerOptions);

  this.updateName(collection.name, $('#collection-name').val());

  this.updateOptions(collection);
};

MarkerCollectionOptions.prototype.getUniqueName = function(originalName) {
  var name = originalName;
  var duplicates = 0;
  while (this.state.markerCollections[name]) {
    name = originalName + ' (' + (++duplicates) + ')';
  }
  return name;
};

MarkerCollectionOptions.prototype.updateName = function(oldName, newName) {
  if (oldName != newName) {
    var newName = this.getUniqueName(newName);
    var collection = this.state.markerCollections[oldName];
    collection.name = newName;
    this.state.selectedCollection = newName;
    this.state.markerCollections[newName] = collection;
    delete this.state.markerCollections[oldName];
    $('#marker-collections .selected span').text(newName);
  }
};

MarkerCollectionOptions.prototype.addCollection = function(name) {
  var that = this;
  if (!name) return;

  var markerCollections = this.state.markerCollections;
  var name = this.getUniqueName(name);

  var collection = markerCollections[name] =
      new MarkerCollection(this.infowindow);
  collection.name = name;
  var markerOptions = this.parseOptions();
  collection.setOptions(markerOptions);

  var div = $('<div/>');
  collection.select = function() {
    // Hides the previously selected collection.
    var oldCollection = markerCollections[that.state.selectedCollection];
    if (oldCollection) oldCollection.setMap(null);
    $('#marker-collections .selected').removeClass('selected');
    that.state.selectedCollection = collection.name;
    div.addClass('selected');
    that.updateOptions(collection);
    // Shows the newly selected collection.
    markerCollections[that.state.selectedCollection].setMap(that.map);
  }

  collection.div = div.addClass('marker-collection')
      .append($('<img/>'))
      .append('<br><span>' + name + '</span>')
      .insertBefore($('#marker-collection-sentinel'))
      .fadeIn()
      .click(collection.select);

  collection.select();
};

MarkerCollectionOptions.prototype.deleteCollection = function(toDelete) {
  if (!confirm('Are you sure you want to delete collection: ' + toDelete)) {
    return;
  }

  var newSelected;
  for (var collection in this.state.markerCollections) {
    if (newSelected && collection == toDelete) {
      break;
    }
    if (collection != toDelete) {
      newSelected = collection;
    }
  }
  
  var collection = this.state.markerCollections[toDelete];
  collection.deleteSelf();
  collection.div.remove();
  delete collection;
  delete this.state.markerCollections[toDelete];

  if (newSelected) {
    this.state.selectedCollection = newSelected;
    this.state.markerCollections[newSelected].select();
  } else {
    this.addCollection('Untitled');
  }
};

function AddMarker(add, state, geocoder) {
  var that = this;
  this.state = state;
  this.add = $(add).submit(function(e) {
    geocoder.geocode({
      address: $('#add-marker-address').val()
    }, function(result, status) {
      if (status != google.maps.GeocoderStatus.OK) {
        alert('Could not understand marker address. Status: ' + status);
      } else {
        that.addMarker(result[0].geometry.location);
      }
    });
    return e.preventDefault();
  });
}

AddMarker.prototype.addMarker = function(latLng) {
  var name = this.state.selectedCollection;
  if (name) {
    this.state.markerCollections[name].addMarker(
        latLng,
        $('#add-marker-title').val(),
        $('#add-marker-content').val());
  }
};
